package iagovsothello.logger;

import iagovsothello.ai.Agent;
import iagovsothello.core.GameState;
import iagovsothello.core.Position;

import java.util.Iterator;


public class BestMovesIterator implements Iterator<Position> {

	private ExperimentContainer container;
	private Agent subject;
	
	private Entry next;
	private Iterator<BasicExperiment> experimentIterator;
	private int currentPlayerNumber;
	private Log[] logs;
	private GameState[] games;
	private int logIndex;
	private Iterator<Entry> entryIterator;
	
	public BestMovesIterator(ExperimentContainer container, Agent subject)
	{
		this.container = container;
		this.subject = subject;
		next = null;
		experimentIterator = null;
		entryIterator = null;
		logs = null;
		games = null;
		init();
	}
	
	@Override
	public boolean hasNext()
	{
		return (next != null);
	}

	@Override
	public Position next() 
	{
		Entry oldNext = next;
		computeNext();
		return oldNext.selectedPosition;
	}

	@Override
	public void remove() 
	{
		throw new UnsupportedOperationException();
	}
	
	private void init()
	{
		experimentIterator = container.experimentIterator();
		iterateExperiment();
	}
	
	private void computeNext()
	{
		iterateEntry();
		if (next == null)
		{
			logIndex++;
			iterateLog();
			if (logIndex >= logs.length)
			{
				iterateExperiment();
			}
		}
	}
	
	private void iterateExperiment()
	{
		boolean found = false;
		if (experimentIterator.hasNext() && !found)
		{
			BasicExperiment bex = experimentIterator.next();
			if (bex.getPlayer1().equals(subject))
				currentPlayerNumber = 1;
			else if (bex.getPlayer2().equals(subject))
				currentPlayerNumber = 2;
			else 
				currentPlayerNumber = 0;
			
			if (currentPlayerNumber > 0)
			{
				logs = bex.getLogs();
				games = bex.getGames();
				logIndex = 0;
				iterateLog();
			}
		}
	}
	
	private void iterateLog()
	{
		while(logIndex < logs.length && games[logIndex].getVictor() != currentPlayerNumber)
		{
			logIndex++;
		}
		if (logIndex < logs.length)
		{
			entryIterator = logs[logIndex].iterator();
			iterateEntry();
		}
	}
	
	private void iterateEntry()
	{
		boolean found = false;
		Entry actual = null;
		while (entryIterator.hasNext() && !found)
		{
			actual = entryIterator.next();
			if (actual.currentPlayer == currentPlayerNumber)
				found = true;
		}
		if (found)
			next = actual;
		else
			next = null;
	}
}
